﻿using System;
using System.Collections.Generic;
using System.Web;

namespace Coding4Fun.Cannon.Web.Common
{
	public class CommonHttpHandler : IHttpHandler
	{
		private static long _currentTickCounter;
		public void ProcessRequest(HttpContext context)
		{
			var returnResult = new Result { QueryString = context.Request.Url.Query };

			// did command pass in a ticks, if not, assume someone is just using a normal web command
			var ignoreTicks = !string.IsNullOrEmpty(context.Request.QueryString["ticks"]);

			long newCommandTicks;
			long.TryParse(context.Request.QueryString["ticks"], out newCommandTicks);

			var command = string.Empty;
			if (!string.IsNullOrEmpty(context.Request.QueryString["command"]))
				command = context.Request.QueryString["command"].Trim().ToLower();
			
			// did command come in after next command already executed
			if (newCommandTicks > _currentTickCounter || ignoreTicks)
			{
				_currentTickCounter = newCommandTicks;
				Dictionary<string, double> data = null;
				try
				{
					switch (command)
					{
						case "init":
							data = Initialize();
							break;
						case "drive":
							int power, leftPower, rightPower;

							if (int.TryParse(context.Request.QueryString["power"], out power))
								Drive(power);
							else if (int.TryParse(context.Request.QueryString["leftpower"], out leftPower) &&
							         int.TryParse(context.Request.QueryString["rightpower"], out rightPower))
								Drive(leftPower, rightPower);

							break;
						case "aim":
							double pan, tilt;

							var hasPan = double.TryParse(context.Request.QueryString["pan"], out pan);
							var hasTilt = double.TryParse(context.Request.QueryString["tilt"], out tilt);

							if (hasPan && hasTilt)
								Aim(pan, tilt);
							else if (hasPan)
								AimPan(pan);
							else if (hasTilt)
								AimTilt(tilt);

							break;
						case "fire":
							Fire();
							break;
						default:
							break;
					}
				}
				catch(Exception ex0)
				{
					returnResult.Data.Add("error", ex0.ToString());
				}

				if (data != null)
					foreach (var item in data)
						returnResult.Data.Add(item.Key, item.Value);

				returnResult.HasExecuted = true;
			}

			returnResult.Command = command;
			returnResult.Time = DateTime.Now;

			context.Response.Write(returnResult.ToString());
		}

		public virtual Dictionary<string, double> Initialize() { return null; }
		
		public virtual void Drive(int power) { }
		public virtual void Drive(int leftPower, int rightPower) { }

		public virtual void Aim(double pan, double tilt) { }
		public virtual void AimPan(double value) { }
		public virtual void AimTilt(double value) { }

		public virtual void Fire() { }

		////are needed?
		//public virtual Result AimRandomly() { return new Result(); }
		//public virtual Result StartCapturingPhotos() { return new Result(); }
		//public virtual Result StopCapturingPhotos() { return new Result(); }
		//public virtual Result GetCapturedPhotos() { return new Result(); }
		//public virtual Result SendToTwitPic() { return new Result(); }

		public bool IsReusable
		{
			get { return true; }
		}
	}
}
